package cmpe451.group7.ourcity.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cmpe451.group7.ourcity.dao.TagDAO;
import cmpe451.group7.ourcity.entity.Tag;
import cmpe451.group7.ourcity.entity.User;

@Repository("tagDAO")
public class TagDAOImpl extends GenericDAOImpl<Tag> implements TagDAO,
		Serializable {

	private static final long serialVersionUID = 1L;

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<Tag> findAll() {
		return super.findAll(Tag.class);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public Tag findByID(long id) {
		return super.findByID(Tag.class, id);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public Tag insertNewTag(String tagName) {
		Session session = this.getCurrentSession();

		Tag t = new Tag();
		t.setTagName(tagName);
		session.save(t);
		//session.flush();

		return t;
	}

	@Override
	@SuppressWarnings("unchecked")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<Tag> findByRestrictions(String tagName) {
		Session session = this.getCurrentSession();
		Criteria criteria = session.createCriteria(Tag.class);

		List<Tag> tags = criteria.add(
				Restrictions.like("tagName", tagName + "%")).list();

		return tags;
	}

	@Override
	@SuppressWarnings("unchecked")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public Tag findByMID(String mID) {
		Session session = this.getCurrentSession();
		Criteria criteria = session.createCriteria(Tag.class);

		List<Tag> tags = criteria.add(Restrictions.like("mID", mID)).list();

		return CollectionUtils.isEmpty(tags) ? null : tags.get(0);
	}

	@SuppressWarnings("unchecked")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<Tag> getTagsofUser(User user) {

		Session session = this.getCurrentSession();

		String hql = "SELECT tags from Comment c JOIN c.tags tags " + "where "
				+ "c.user.userID like :pn " + "group by tags.tagID ";

		Query query = session.createQuery(hql);
		query.setParameter("pn", user.getUserID());

		List<Tag> commentTags = query.list();

		if (commentTags == null)
			return new ArrayList<Tag>();

		return commentTags;
	}

	@Override
	@Transactional
	public Tag saveIfNotExists(Tag t) {
		Session session = this.getCurrentSession();

		String hql = "SELECT count(t) from Tag t WHERE tagName = :tag_name";

		Query query = session.createQuery(hql);
		query.setParameter("tag_name", t.getTagName());

		Long count = (Long) query.uniqueResult();
		if (count == 0) {
			save(t);
			return t;
		} else {
			return null;
		}
	}
}
